 bondscell_results $005b40d9-bd89-4491-9807-d33a6c674b75queued¤logsrunning¦outputbodymsg5MethodError: objects of type Nothing are not callablestacktracecall_shorttop-level scopeinlinedãurlpathp/home/runner/work/disorganised-mess/disorganised-mess/reactive python.jl#==#005b40d9-bd89-4491-9807-d33a6c674b75source_packagecalltop-level scopelinfo_typeNothinglinefile:reactive python.jl#==#005b40d9-bd89-4491-9807-d33a6c674b75func##function_wrapped_cell#308parent_modulefrom_c¤mime'application/vnd.pluto.stacktrace+objectrootassigneelast_run_timestampAgCpersist_js_state·has_pluto_hook_features§cell_id$005b40d9-bd89-4491-9807-d33a6c674b75depends_on_disabled_cells§runtimepublished_object_keysdepends_on_skipped_cells§errored$12814f02-7e90-401a-9573-5c6b2f8067aequeued¤logsrunning¦outputbodymimetext/plainrootassigneelast_run_timestampAbD<Kpersist_js_state·has_pluto_hook_features§cell_id$12814f02-7e90-401a-9573-5c6b2f8067aedepends_on_disabled_cells§runtimecpublished_object_keysdepends_on_skipped_cells§errored$6449e96f-19ce-4100-8b35-56113bc24b7dqueued¤logsrunning¦outputbodyExpr
  head: Symbol macrocall
  args: Array{Any}((3,))
    1: Symbol @py_str
    2: LineNumberNode
      line: Int64 1
      file: Symbol /home/runner/work/disorganised-mess/disorganised-mess/reactive python.jl#==#6449e96f-19ce-4100-8b35-56113bc24b7d
    3: String "[1+1]"
mimetext/plainrootassigneelast_run_timestampAgGpersist_js_state·has_pluto_hook_features§cell_id$6449e96f-19ce-4100-8b35-56113bc24b7ddepends_on_disabled_cells§runtime 7ɵpublished_object_keysdepends_on_skipped_cells§errored$5f5ab869-c551-42d3-9325-86ecdc424c9bqueued¤logsrunning¦outputbody"@pyr_old_str (macro with 1 method)mimetext/plainrootassigneelast_run_timestampAhәpersist_js_state·has_pluto_hook_features§cell_id$5f5ab869-c551-42d3-9325-86ecdc424c9bdepends_on_disabled_cells§runtime vpublished_object_keysdepends_on_skipped_cells§errored$56a3a022-6ed3-47d8-8d62-ce4ead5ca026queued¤logsrunning¦outputbodymsg#UndefVarError: @pyr_str not definedstacktracecall_shorttop-level scopeinlined£urlpathsource_packagecalltop-level scopelinfo_typeNothingline filefunctop-level scopeparent_modulefrom_ccall_short#macroexpand#51inlinedãurlpath./expr.jlsource_packagecall#macroexpand#51linfo_typeNothinglineufileexpr.jlfunc#macroexpand#51parent_modulefrom_ccall_shorttop-level scopeinlinedãurlpathp/home/runner/work/disorganised-mess/disorganised-mess/reactive python.jl#==#56a3a022-6ed3-47d8-8d62-ce4ead5ca026source_packagecalltop-level scopelinfo_typeNothinglinefile:reactive python.jl#==#56a3a022-6ed3-47d8-8d62-ce4ead5ca026func##function_wrapped_cell#322parent_modulefrom_c¤mime'application/vnd.pluto.stacktrace+objectrootassigneelast_run_timestampAhpersist_js_state·has_pluto_hook_features§cell_id$56a3a022-6ed3-47d8-8d62-ce4ead5ca026depends_on_disabled_cells§runtimepublished_object_keysdepends_on_skipped_cells§errored$e07e4a47-a3cc-4ca4-a946-29e7df33ec6dqueued¤logsrunning¦outputbody<div class="markdown"><h1>Reactive Python</h1>
<p>The <code>pyr&quot;</code> macro is just like the <code>py&quot;</code> macro from <code>PyCall.jl</code>, except it is reactive&#33; This means:</p>
<ul>
<li><p>If you define a Python variable, then other cells that use that python variable are also evaluated.</p>
</li>
<li><p>The scope of Python variables is cleaned up automatically.</p>
</li>
<li><p>Multiple definitions are not allowed.</p>
</li>
</ul>
<p>This is using the Python port of Pluto.ExpressionExplorer by Mikołaj Bochenski: <a href="https://github.com/lightning-notebook/engine">https://github.com/lightning-notebook/engine</a> and some Julia macro magic.</p>
</div>mimetext/htmlrootassigneelast_run_timestampAg\;dpersist_js_state÷has_pluto_hook_features§cell_id$e07e4a47-a3cc-4ca4-a946-29e7df33ec6ddepends_on_disabled_cells§runtimeTpublished_object_keysdepends_on_skipped_cells§errored$56fcc0c2-0ce0-445b-b602-6525bab173b3queued¤logsrunning¦outputbodyelements0.747367text/plainnothingtext/plaintypeTupleobjectid8e3a45e69275c07bmime!application/vnd.pluto.tree+objectrootassigneelast_run_timestampAhipersist_js_state·has_pluto_hook_features§cell_id$56fcc0c2-0ce0-445b-b602-6525bab173b3depends_on_disabled_cells§runtime a?published_object_keysdepends_on_skipped_cells§errored$21199966-adc3-498e-87ae-62333810efb5queued¤logsrunning¦outputbodyquote
    #= /home/runner/work/disorganised-mess/disorganised-mess/reactive python.jl#==#5c432b4e-60e0-4288-8d5a-42e364ce8d16:8 =#
    begin
        #= /home/runner/work/disorganised-mess/disorganised-mess/reactive python.jl#==#5c432b4e-60e0-4288-8d5a-42e364ce8d16:12 =#
        let s = var"py#var_b"
            #= /home/runner/work/disorganised-mess/disorganised-mess/reactive python.jl#==#5c432b4e-60e0-4288-8d5a-42e364ce8d16:13 =#
            begin
                #= /home/runner/work/disorganised-mess/disorganised-mess/reactive python.jl#==#b9903477-5070-43eb-82a9-8b750f79c8fa:25 =#
                var"#471#m" = Main.workspace#4.pynamespace(Main.workspace#4.Main)
                #= /home/runner/work/disorganised-mess/disorganised-mess/reactive python.jl#==#b9903477-5070-43eb-82a9-8b750f79c8fa:26 =#
                begin
                    var"#471#m"["__julia_localvar_25_1"] = Main.workspace#4.PyObject(s)
                end
                #= /home/runner/work/disorganised-mess/disorganised-mess/reactive python.jl#==#b9903477-5070-43eb-82a9-8b750f79c8fa:27 =#
                var"#472#ret" = (PyAny)(Main.workspace#4.pyeval_(Base.string("b = __julia_localvar_25_1\n"), var"#471#m", var"#471#m", 257, "/home/runner/work/disorganised-mess/disorganised-mess/reactive python.jl#==#b9903477-5070-43eb-82a9-8b750f79c8fa"))
                #= /home/runner/work/disorganised-mess/disorganised-mess/reactive python.jl#==#b9903477-5070-43eb-82a9-8b750f79c8fa:28 =#
                nothing
                #= /home/runner/work/disorganised-mess/disorganised-mess/reactive python.jl#==#b9903477-5070-43eb-82a9-8b750f79c8fa:29 =#
                var"#472#ret"
            end
        end
    end
    #= /home/runner/work/disorganised-mess/disorganised-mess/reactive python.jl#==#5c432b4e-60e0-4288-8d5a-42e364ce8d16:19 =#
    var"#470#output" = begin
            #= /home/runner/work/disorganised-mess/disorganised-mess/reactive python.jl#==#b9903477-5070-43eb-82a9-8b750f79c8fa:25 =#
            var"#473#m" = Main.workspace#4.pynamespace(Main.workspace#4.Main)
            #= /home/runner/work/disorganised-mess/disorganised-mess/reactive python.jl#==#b9903477-5070-43eb-82a9-8b750f79c8fa:26 =#
            begin
            end
            #= /home/runner/work/disorganised-mess/disorganised-mess/reactive python.jl#==#b9903477-5070-43eb-82a9-8b750f79c8fa:27 =#
            var"#474#ret" = (PyAny)(Main.workspace#4.pyeval_((Main.workspace#5.Base).string("x = 123\ny = b\n"), var"#473#m", var"#473#m", 257, "/home/runner/work/disorganised-mess/disorganised-mess/reactive python.jl#==#b9903477-5070-43eb-82a9-8b750f79c8fa"))
            #= /home/runner/work/disorganised-mess/disorganised-mess/reactive python.jl#==#b9903477-5070-43eb-82a9-8b750f79c8fa:28 =#
            nothing
            #= /home/runner/work/disorganised-mess/disorganised-mess/reactive python.jl#==#b9903477-5070-43eb-82a9-8b750f79c8fa:29 =#
            var"#474#ret"
        end
    #= /home/runner/work/disorganised-mess/disorganised-mess/reactive python.jl#==#5c432b4e-60e0-4288-8d5a-42e364ce8d16:23 =#
    begin
        #= /home/runner/work/disorganised-mess/disorganised-mess/reactive python.jl#==#5c432b4e-60e0-4288-8d5a-42e364ce8d16:27 =#
        var"py#var_x" = begin
                #= /home/runner/work/disorganised-mess/disorganised-mess/reactive python.jl#==#b9903477-5070-43eb-82a9-8b750f79c8fa:25 =#
                var"#475#m" = Main.workspace#4.pynamespace(Main.workspace#4.Main)
                #= /home/runner/work/disorganised-mess/disorganised-mess/reactive python.jl#==#b9903477-5070-43eb-82a9-8b750f79c8fa:26 =#
                begin
                end
                #= /home/runner/work/disorganised-mess/disorganised-mess/reactive python.jl#==#b9903477-5070-43eb-82a9-8b750f79c8fa:27 =#
                var"#476#ret" = (PyAny)(Main.workspace#4.pyeval_(Base.string("x"), var"#475#m", var"#475#m", 258, "/home/runner/work/disorganised-mess/disorganised-mess/reactive python.jl#==#b9903477-5070-43eb-82a9-8b750f79c8fa"))
                #= /home/runner/work/disorganised-mess/disorganised-mess/reactive python.jl#==#b9903477-5070-43eb-82a9-8b750f79c8fa:28 =#
                begin
                end
                #= /home/runner/work/disorganised-mess/disorganised-mess/reactive python.jl#==#b9903477-5070-43eb-82a9-8b750f79c8fa:29 =#
                var"#476#ret"
            end
    end
    begin
        #= /home/runner/work/disorganised-mess/disorganised-mess/reactive python.jl#==#5c432b4e-60e0-4288-8d5a-42e364ce8d16:27 =#
        var"py#var_y" = begin
                #= /home/runner/work/disorganised-mess/disorganised-mess/reactive python.jl#==#b9903477-5070-43eb-82a9-8b750f79c8fa:25 =#
                var"#477#m" = Main.workspace#4.pynamespace(Main.workspace#4.Main)
                #= /home/runner/work/disorganised-mess/disorganised-mess/reactive python.jl#==#b9903477-5070-43eb-82a9-8b750f79c8fa:26 =#
                begin
                end
                #= /home/runner/work/disorganised-mess/disorganised-mess/reactive python.jl#==#b9903477-5070-43eb-82a9-8b750f79c8fa:27 =#
                var"#478#ret" = (PyAny)(Main.workspace#4.pyeval_(Base.string("y"), var"#477#m", var"#477#m", 258, "/home/runner/work/disorganised-mess/disorganised-mess/reactive python.jl#==#b9903477-5070-43eb-82a9-8b750f79c8fa"))
                #= /home/runner/work/disorganised-mess/disorganised-mess/reactive python.jl#==#b9903477-5070-43eb-82a9-8b750f79c8fa:28 =#
                begin
                end
                #= /home/runner/work/disorganised-mess/disorganised-mess/reactive python.jl#==#b9903477-5070-43eb-82a9-8b750f79c8fa:29 =#
                var"#478#ret"
            end
    end
    #= /home/runner/work/disorganised-mess/disorganised-mess/reactive python.jl#==#5c432b4e-60e0-4288-8d5a-42e364ce8d16:31 =#
    var"#470#output"
endmimetext/plainrootassigneelast_run_timestampAh5persist_js_state·has_pluto_hook_features§cell_id$21199966-adc3-498e-87ae-62333810efb5depends_on_disabled_cells§runtime published_object_keysdepends_on_skipped_cells§errored$73c3f448-be7d-49b7-9e39-18c3a08feb01queued¤logsrunning¦outputbodymimetext/plainrootassigneelast_run_timestampAhpersist_js_state·has_pluto_hook_features§cell_id$73c3f448-be7d-49b7-9e39-18c3a08feb01depends_on_disabled_cells§runtime	published_object_keysdepends_on_skipped_cells§errored$fb3fb09d-1ba7-431e-aba2-f832d259075aqueued¤logsrunning¦outputbody1123124mimetext/plainrootassigneelast_run_timestampAh諰persist_js_state·has_pluto_hook_features§cell_id$fb3fb09d-1ba7-431e-aba2-f832d259075adepends_on_disabled_cells§runtime Zpublished_object_keysdepends_on_skipped_cells§errored$8e0722dc-6a3d-4cb3-ac8e-c527f123d0a7queued¤logsrunning¦outputbodymimetext/plainrootassigneelast_run_timestampAfpersist_js_state·has_pluto_hook_features§cell_id$8e0722dc-6a3d-4cb3-ac8e-c527f123d0a7depends_on_disabled_cells§runtime published_object_keysdepends_on_skipped_cells§errored$600344b6-ff43-431b-b858-2bf30e93d938queued¤logsrunning¦outputbody<div class="markdown"><p>Following code is from <a href="https://github.com/lightning-notebook/engine/blob/master/tests/test_variable_access.py">https://github.com/lightning-notebook/engine/blob/master/tests/test<em>variable</em>access.py</a></p>
</div>mimetext/htmlrootassigneelast_run_timestampAg^Mbpersist_js_state÷has_pluto_hook_features§cell_id$600344b6-ff43-431b-b858-2bf30e93d938depends_on_disabled_cells§runtime9published_object_keysdepends_on_skipped_cells§errored$688c93e7-b50f-4bb7-ab23-5686fd8ffb18queued¤logsrunning¦outputbody2mimetext/plainrootassigneelast_run_timestampAh@썰persist_js_state·has_pluto_hook_features§cell_id$688c93e7-b50f-4bb7-ab23-5686fd8ffb18depends_on_disabled_cells§runtime}published_object_keysdepends_on_skipped_cells§errored$a1ada27d-8a1a-453a-ace7-ae07b68ad42aqueued¤logsrunning¦outputbody123mimetext/plainrootassigneelast_run_timestampAbDpersist_js_state·has_pluto_hook_features§cell_id$a1ada27d-8a1a-453a-ace7-ae07b68ad42adepends_on_disabled_cells§runtimepublished_object_keysdepends_on_skipped_cells§errored$b9903477-5070-43eb-82a9-8b750f79c8faqueued¤logsrunning¦outputbody$@custom_py_str (macro with 1 method)mimetext/plainrootassigneelast_run_timestampAh!persist_js_state·has_pluto_hook_features§cell_id$b9903477-5070-43eb-82a9-8b750f79c8fadepends_on_disabled_cells§runtime Gmzpublished_object_keysdepends_on_skipped_cells§errored$71ca495d-39ad-4d52-94a5-d4248679ce1equeued¤logsrunning¦outputbodyprefixPyCall.PyObjectelementsPyObject frozenset()text/plainPyObject frozenset({'x'})text/plaintypeArrayprefix_shortobjectid26cd57b35a0b609mime!application/vnd.pluto.tree+objectrootassigneerwlast_run_timestampAhqpersist_js_state·has_pluto_hook_features§cell_id$71ca495d-39ad-4d52-94a5-d4248679ce1edepends_on_disabled_cells§runtime40published_object_keysdepends_on_skipped_cells§errored$5c432b4e-60e0-4288-8d5a-42e364ce8d16queued¤logsrunning¦outputbody@pyr_str (macro with 1 method)mimetext/plainrootassigneelast_run_timestampAh0#persist_js_state·has_pluto_hook_features§cell_id$5c432b4e-60e0-4288-8d5a-42e364ce8d16depends_on_disabled_cells§runtime %z+published_object_keysdepends_on_skipped_cells§errored$f4d3b313-1c8c-4de1-b5bd-592cb1112068queued¤logsrunning¦outputbodyprefixInt64elements2text/plain4text/plaintypeArrayprefix_shortobjectidd34fe57a218fd7d9mime!application/vnd.pluto.tree+objectrootassigneelast_run_timestampAhТpersist_js_state·has_pluto_hook_features§cell_id$f4d3b313-1c8c-4de1-b5bd-592cb1112068depends_on_disabled_cells§runtime:published_object_keysdepends_on_skipped_cells§errored$5dc1c311-1004-4056-b0a9-06622546486equeued¤logsrunning¦outputbody123123mimetext/plainrootassigneelast_run_timestampAh̰persist_js_state·has_pluto_hook_features§cell_id$5dc1c311-1004-4056-b0a9-06622546486edepends_on_disabled_cells§runtime Apublished_object_keysdepends_on_skipped_cells§errored$7576c6f6-3fc8-453a-b4c8-fe0c53b9ed7equeued¤logsrunning¦outputbodymimetext/plainrootassigneelast_run_timestampAbD[persist_js_state·has_pluto_hook_features§cell_id$7576c6f6-3fc8-453a-b4c8-fe0c53b9ed7edepends_on_disabled_cells§runtime!published_object_keysdepends_on_skipped_cells§errored$6a35c5b8-2ce0-11ec-3a8c-b5a25bab9f9bqueued¤logsrunning¦outputbodymimetext/plainrootassigneelast_run_timestampAf0spersist_js_state·has_pluto_hook_features§cell_id$6a35c5b8-2ce0-11ec-3a8c-b5a25bab9f9bdepends_on_disabled_cells§runtimeYpublished_object_keysdepends_on_skipped_cells§errored$d9bc5dc1-67b6-47c6-9592-3b474ec451a0queued¤logsrunning¦outputbodyExpr
  head: Symbol macrocall
  args: Array{Any}((3,))
    1: Symbol @py_str
    2: LineNumberNode
      line: Int64 1
      file: Symbol /home/runner/work/disorganised-mess/disorganised-mess/reactive python.jl#==#d9bc5dc1-67b6-47c6-9592-3b474ec451a0
    3: String "[1+1]\n"
mimetext/plainrootassigneelast_run_timestampAgշpersist_js_state·has_pluto_hook_features§cell_id$d9bc5dc1-67b6-47c6-9592-3b474ec451a0depends_on_disabled_cells§runtime Ԉpublished_object_keysdepends_on_skipped_cells§errored$e8873c23-139d-41bc-be35-ebd636e48aeequeued¤logsrunning¦outputbody0.9092974268256817mimetext/plainrootassigneelast_run_timestampAg!ٰpersist_js_state·has_pluto_hook_features§cell_id$e8873c23-139d-41bc-be35-ebd636e48aeedepends_on_disabled_cells§runtimemcpublished_object_keysdepends_on_skipped_cells§errored$d74aed51-9542-47aa-8c3d-fb634c1a0212queued¤logsrunning¦outputbody2PyObject <function reads_writes at 0x7fd600fd87c0>mimetext/plainrootassigneepy_reads_writeslast_run_timestampAhPƤpersist_js_state·has_pluto_hook_features§cell_id$d74aed51-9542-47aa-8c3d-fb634c1a0212depends_on_disabled_cells§runtimeopublished_object_keysdepends_on_skipped_cells§errored$ab92a31d-1ef4-427f-b1c7-fa2790278a14queued¤logsrunning¦outputbodyprefixAnyelements"x"text/plaintypeArrayprefix_shortobjectid366f9610a9dc99emime!application/vnd.pluto.tree+objectrootassigneelast_run_timestampAhǰpersist_js_state·has_pluto_hook_features§cell_id$ab92a31d-1ef4-427f-b1c7-fa2790278a14depends_on_disabled_cells§runtime ?ppublished_object_keysdepends_on_skipped_cells§errored$b59d932b-6425-47c2-a67d-208113bc8b7bqueued¤logsrunning¦outputbodymimetext/plainrootassigneelast_run_timestampAggspersist_js_state·has_pluto_hook_features§cell_id$b59d932b-6425-47c2-a67d-208113bc8b7bdepends_on_disabled_cells§runtime⣵published_object_keysdepends_on_skipped_cells§errored$fdd2e0ae-7ac9-4da7-9bfb-41d7cf76296bqueued¤logsrunning¦outputbody3mimetext/plainrootassigneelast_run_timestampAh>bpersist_js_state·has_pluto_hook_features§cell_id$fdd2e0ae-7ac9-4da7-9bfb-41d7cf76296bdepends_on_disabled_cells§runtimeqpublished_object_keysdepends_on_skipped_cells§errored$d3fe9870-ac9d-4871-b8cc-1361a446b0a5queued¤logsrunning¦outputbodymimetext/plainrootassigneelast_run_timestampAh&tpersist_js_state·has_pluto_hook_features§cell_id$d3fe9870-ac9d-4871-b8cc-1361a446b0a5depends_on_disabled_cells§runtime 
published_object_keysdepends_on_skipped_cells§errored$dd20f208-0e39-4255-b35a-a8189986a165queued¤logsrunning¦outputbodymimetext/plainrootassigneelast_run_timestampAhypersist_js_state·has_pluto_hook_features§cell_id$dd20f208-0e39-4255-b35a-a8189986a165depends_on_disabled_cells§runtime 
$published_object_keysdepends_on_skipped_cells§errored$f93f0eef-bb0c-45ee-a080-e8eeb6611176queued¤logsrunning¦outputbodymimetext/plainrootassigneelast_run_timestampAh0persist_js_state·has_pluto_hook_features§cell_id$f93f0eef-bb0c-45ee-a080-e8eeb6611176depends_on_disabled_cells§runtime -published_object_keysdepends_on_skipped_cells§errored$216e88b3-82cb-4d74-aae4-c21791980ac2queued¤logsrunning¦outputbodymimetext/plainrootassigneelast_run_timestampAhxpersist_js_state·has_pluto_hook_features§cell_id$216e88b3-82cb-4d74-aae4-c21791980ac2depends_on_disabled_cells§runtime 	2published_object_keysdepends_on_skipped_cells§errored±cell_dependencies $005b40d9-bd89-4491-9807-d33a6c674b75precedence_heuristic	cell_id$005b40d9-bd89-4491-9807-d33a6c674b75downstream_cells_map#414#m#415#retupstream_cells_mapBase.stringBasePyCall.pynamespace@py_str#___this_pluto_module_namePyCall$6a35c5b8-2ce0-11ec-3a8c-b5a25bab9f9bPyCall.pyeval_$12814f02-7e90-401a-9573-5c6b2f8067aeprecedence_heuristic	cell_id$12814f02-7e90-401a-9573-5c6b2f8067aedownstream_cells_mapupstream_cells_map$6449e96f-19ce-4100-8b35-56113bc24b7dprecedence_heuristic	cell_id$6449e96f-19ce-4100-8b35-56113bc24b7ddownstream_cells_mapupstream_cells_mapDump$5f5ab869-c551-42d3-9325-86ecdc424c9bprecedence_heuristic	cell_id$5f5ab869-c551-42d3-9325-86ecdc424c9bdownstream_cells_map@pyr_old_strupstream_cells_mappy_reads_writes$d74aed51-9542-47aa-8c3d-fb634c1a0212esc@custom_py_str$b9903477-5070-43eb-82a9-8b750f79c8faSymbol$56a3a022-6ed3-47d8-8d62-ce4ead5ca026precedence_heuristic	cell_id$56a3a022-6ed3-47d8-8d62-ce4ead5ca026downstream_cells_mapupstream_cells_mapMetaBaseMeta.macroexpand@__MODULE__#___this_pluto_module_nameBase.remove_linenums!$e07e4a47-a3cc-4ca4-a946-29e7df33ec6dprecedence_heuristic	cell_id$e07e4a47-a3cc-4ca4-a946-29e7df33ec6ddownstream_cells_mapupstream_cells_map@md_strgetindex$56fcc0c2-0ce0-445b-b602-6525bab173b3precedence_heuristic	cell_id$56fcc0c2-0ce0-445b-b602-6525bab173b3downstream_cells_mapupstream_cells_map#py_var_xrand$21199966-adc3-498e-87ae-62333810efb5precedence_heuristic	cell_id$21199966-adc3-498e-87ae-62333810efb5downstream_cells_mapupstream_cells_mapBase@macroexpandBase.macroexpand#___this_pluto_module_name@pyr_str$5c432b4e-60e0-4288-8d5a-42e364ce8d16$73c3f448-be7d-49b7-9e39-18c3a08feb01precedence_heuristic	cell_id$73c3f448-be7d-49b7-9e39-18c3a08feb01downstream_cells_map#431#retpy#var_y$f4d3b313-1c8c-4de1-b5bd-592cb1112068#433#ret#432#m#427#output#430#mupstream_cells_mapBase.stringMainBasepyeval_$d3fe9870-ac9d-4871-b8cc-1361a446b0a5PyObjectpynamespace$d3fe9870-ac9d-4871-b8cc-1361a446b0a5@pyr_str$5c432b4e-60e0-4288-8d5a-42e364ce8d16py#var_x$f93f0eef-bb0c-45ee-a080-e8eeb6611176$fb3fb09d-1ba7-431e-aba2-f832d259075aprecedence_heuristic	cell_id$fb3fb09d-1ba7-431e-aba2-f832d259075adownstream_cells_map#452#m#453#ret#449#outputupstream_cells_mapBase.stringMainBasepy#var_f$216e88b3-82cb-4d74-aae4-c21791980ac2PyObjectpynamespace$d3fe9870-ac9d-4871-b8cc-1361a446b0a5@pyr_str$5c432b4e-60e0-4288-8d5a-42e364ce8d16pyeval_$d3fe9870-ac9d-4871-b8cc-1361a446b0a5$8e0722dc-6a3d-4cb3-ac8e-c527f123d0a7precedence_heuristiccell_id$8e0722dc-6a3d-4cb3-ac8e-c527f123d0a7downstream_cells_mapPkgupstream_cells_map$600344b6-ff43-431b-b858-2bf30e93d938precedence_heuristic	cell_id$600344b6-ff43-431b-b858-2bf30e93d938downstream_cells_mapupstream_cells_map@md_strgetindex$688c93e7-b50f-4bb7-ab23-5686fd8ffb18precedence_heuristic	cell_id$688c93e7-b50f-4bb7-ab23-5686fd8ffb18downstream_cells_map#422#ret#421#mupstream_cells_mapBase.stringMainBase@custom_py_str$b9903477-5070-43eb-82a9-8b750f79c8fapynamespace$d3fe9870-ac9d-4871-b8cc-1361a446b0a5pyeval_$d3fe9870-ac9d-4871-b8cc-1361a446b0a5$a1ada27d-8a1a-453a-ace7-ae07b68ad42aprecedence_heuristic	cell_id$a1ada27d-8a1a-453a-ace7-ae07b68ad42adownstream_cells_mapupstream_cells_map$b9903477-5070-43eb-82a9-8b750f79c8faprecedence_heuristic	cell_id$b9903477-5070-43eb-82a9-8b750f79c8fadownstream_cells_map@custom_py_str$fdd2e0ae-7ac9-4da7-9bfb-41d7cf76296b$5c432b4e-60e0-4288-8d5a-42e364ce8d16$5f5ab869-c551-42d3-9325-86ecdc424c9b$688c93e7-b50f-4bb7-ab23-5686fd8ffb18upstream_cells_map CorefirstindexlastindexkeysescfilterPyObjectStringExprnothinglengthPy_file_input$d3fe9870-ac9d-4871-b8cc-1361a446b0a5==ininterpolate_pycode$d3fe9870-ac9d-4871-b8cc-1361a446b0a5make_fname$d3fe9870-ac9d-4871-b8cc-1361a446b0a5@__FILE__:collectprevindIntegerisapush!sort!Py_eval_input$d3fe9870-ac9d-4871-b8cc-1361a446b0a5PyAnyCore._expr$71ca495d-39ad-4d52-94a5-d4248679ce1eprecedence_heuristic	cell_id$71ca495d-39ad-4d52-94a5-d4248679ce1edownstream_cells_maprw$ab92a31d-1ef4-427f-b1c7-fa2790278a14upstream_cells_mappy_reads_writes$d74aed51-9542-47aa-8c3d-fb634c1a0212$5c432b4e-60e0-4288-8d5a-42e364ce8d16precedence_heuristic	cell_id$5c432b4e-60e0-4288-8d5a-42e364ce8d16downstream_cells_map@pyr_str$73c3f448-be7d-49b7-9e39-18c3a08feb01$f93f0eef-bb0c-45ee-a080-e8eeb6611176$f4d3b313-1c8c-4de1-b5bd-592cb1112068$dd20f208-0e39-4255-b35a-a8189986a165$5dc1c311-1004-4056-b0a9-06622546486e$21199966-adc3-498e-87ae-62333810efb5$fb3fb09d-1ba7-431e-aba2-f832d259075a$216e88b3-82cb-4d74-aae4-c21791980ac2upstream_cells_mappy_reads_writes$d74aed51-9542-47aa-8c3d-fb634c1a0212esc@custom_py_str$b9903477-5070-43eb-82a9-8b750f79c8faSymbol$f4d3b313-1c8c-4de1-b5bd-592cb1112068precedence_heuristic	cell_id$f4d3b313-1c8c-4de1-b5bd-592cb1112068downstream_cells_map#459#m#460#ret#454#outputupstream_cells_mapBase.stringMainBasepyeval_$d3fe9870-ac9d-4871-b8cc-1361a446b0a5py#var_y$73c3f448-be7d-49b7-9e39-18c3a08feb01PyObjectpynamespace$d3fe9870-ac9d-4871-b8cc-1361a446b0a5@pyr_str$5c432b4e-60e0-4288-8d5a-42e364ce8d16py#var_x$f93f0eef-bb0c-45ee-a080-e8eeb6611176$5dc1c311-1004-4056-b0a9-06622546486eprecedence_heuristic	cell_id$5dc1c311-1004-4056-b0a9-06622546486edownstream_cells_map#467#ret#466#m#461#outputupstream_cells_mapBase.stringMainBasepyeval_$d3fe9870-ac9d-4871-b8cc-1361a446b0a5PyObjectpy#var_cool$dd20f208-0e39-4255-b35a-a8189986a165pynamespace$d3fe9870-ac9d-4871-b8cc-1361a446b0a5@pyr_str$5c432b4e-60e0-4288-8d5a-42e364ce8d16py#var_x$f93f0eef-bb0c-45ee-a080-e8eeb6611176$7576c6f6-3fc8-453a-b4c8-fe0c53b9ed7eprecedence_heuristic	cell_id$7576c6f6-3fc8-453a-b4c8-fe0c53b9ed7edownstream_cells_mapupstream_cells_map$6a35c5b8-2ce0-11ec-3a8c-b5a25bab9f9bprecedence_heuristiccell_id$6a35c5b8-2ce0-11ec-3a8c-b5a25bab9f9bdownstream_cells_mapPyCall$e8873c23-139d-41bc-be35-ebd636e48aee$005b40d9-bd89-4491-9807-d33a6c674b75$d74aed51-9542-47aa-8c3d-fb634c1a0212upstream_cells_map$d9bc5dc1-67b6-47c6-9592-3b474ec451a0precedence_heuristic	cell_id$d9bc5dc1-67b6-47c6-9592-3b474ec451a0downstream_cells_mapupstream_cells_mapDump$e8873c23-139d-41bc-be35-ebd636e48aeeprecedence_heuristic	cell_id$e8873c23-139d-41bc-be35-ebd636e48aeedownstream_cells_map#419#ret#417#ret#418#m#416#mupstream_cells_mapBase.stringBasePyCall.pynamespace@py_str#___this_pluto_module_namePyCall$6a35c5b8-2ce0-11ec-3a8c-b5a25bab9f9bPyCall.pyeval_$d74aed51-9542-47aa-8c3d-fb634c1a0212precedence_heuristic	cell_id$d74aed51-9542-47aa-8c3d-fb634c1a0212downstream_cells_map#413#ret#412#mpy_reads_writes$71ca495d-39ad-4d52-94a5-d4248679ce1e$5c432b4e-60e0-4288-8d5a-42e364ce8d16$5f5ab869-c551-42d3-9325-86ecdc424c9b#410#m#411#retupstream_cells_mapBase.stringBasePyCall.pynamespace@py_str#___this_pluto_module_namePyCall$6a35c5b8-2ce0-11ec-3a8c-b5a25bab9f9bPyCall.pyeval_$ab92a31d-1ef4-427f-b1c7-fa2790278a14precedence_heuristic	cell_id$ab92a31d-1ef4-427f-b1c7-fa2790278a14downstream_cells_mapupstream_cells_maprw$71ca495d-39ad-4d52-94a5-d4248679ce1ecollect|>$b59d932b-6425-47c2-a67d-208113bc8b7bprecedence_heuristiccell_id$b59d932b-6425-47c2-a67d-208113bc8b7bdownstream_cells_mapPlutoUIupstream_cells_map$fdd2e0ae-7ac9-4da7-9bfb-41d7cf76296bprecedence_heuristic	cell_id$fdd2e0ae-7ac9-4da7-9bfb-41d7cf76296bdownstream_cells_map#426#ret#424#ret#425#m#423#mupstream_cells_mapBase.stringMainBase@custom_py_str$b9903477-5070-43eb-82a9-8b750f79c8fapynamespace$d3fe9870-ac9d-4871-b8cc-1361a446b0a5pyeval_$d3fe9870-ac9d-4871-b8cc-1361a446b0a5$d3fe9870-ac9d-4871-b8cc-1361a446b0a5precedence_heuristic	cell_id$d3fe9870-ac9d-4871-b8cc-1361a446b0a5downstream_cells_mapmake_fname$b9903477-5070-43eb-82a9-8b750f79c8faPy_file_input$b9903477-5070-43eb-82a9-8b750f79c8faPy_eval_input$b9903477-5070-43eb-82a9-8b750f79c8fapynamespace$73c3f448-be7d-49b7-9e39-18c3a08feb01$f93f0eef-bb0c-45ee-a080-e8eeb6611176$f4d3b313-1c8c-4de1-b5bd-592cb1112068$dd20f208-0e39-4255-b35a-a8189986a165$5dc1c311-1004-4056-b0a9-06622546486e$fdd2e0ae-7ac9-4da7-9bfb-41d7cf76296b$fb3fb09d-1ba7-431e-aba2-f832d259075a$216e88b3-82cb-4d74-aae4-c21791980ac2$688c93e7-b50f-4bb7-ab23-5686fd8ffb18interpolate_pycode$b9903477-5070-43eb-82a9-8b750f79c8fapyeval_$73c3f448-be7d-49b7-9e39-18c3a08feb01$f93f0eef-bb0c-45ee-a080-e8eeb6611176$f4d3b313-1c8c-4de1-b5bd-592cb1112068$dd20f208-0e39-4255-b35a-a8189986a165$5dc1c311-1004-4056-b0a9-06622546486e$fdd2e0ae-7ac9-4da7-9bfb-41d7cf76296b$fb3fb09d-1ba7-431e-aba2-f832d259075a$216e88b3-82cb-4d74-aae4-c21791980ac2$688c93e7-b50f-4bb7-ab23-5686fd8ffb18upstream_cells_map$dd20f208-0e39-4255-b35a-a8189986a165precedence_heuristic	cell_id$dd20f208-0e39-4255-b35a-a8189986a165downstream_cells_map#438#ret#434#output#435#m#436#ret#437#mpy#var_cool$5dc1c311-1004-4056-b0a9-06622546486eupstream_cells_mapBase.stringMainBasepynamespace$d3fe9870-ac9d-4871-b8cc-1361a446b0a5@pyr_str$5c432b4e-60e0-4288-8d5a-42e364ce8d16pyeval_$d3fe9870-ac9d-4871-b8cc-1361a446b0a5$f93f0eef-bb0c-45ee-a080-e8eeb6611176precedence_heuristic	cell_id$f93f0eef-bb0c-45ee-a080-e8eeb6611176downstream_cells_map#447#m#444#output#448#ret#445#m#446#retpy#var_x$73c3f448-be7d-49b7-9e39-18c3a08feb01$f4d3b313-1c8c-4de1-b5bd-592cb1112068$5dc1c311-1004-4056-b0a9-06622546486eupstream_cells_mapBase.stringMainBasepynamespace$d3fe9870-ac9d-4871-b8cc-1361a446b0a5@pyr_str$5c432b4e-60e0-4288-8d5a-42e364ce8d16pyeval_$d3fe9870-ac9d-4871-b8cc-1361a446b0a5$216e88b3-82cb-4d74-aae4-c21791980ac2precedence_heuristic	cell_id$216e88b3-82cb-4d74-aae4-c21791980ac2downstream_cells_map#440#mpy#var_f$fb3fb09d-1ba7-431e-aba2-f832d259075a#441#ret#443#ret#442#m#439#outputupstream_cells_mapBase.stringMainBasepynamespace$d3fe9870-ac9d-4871-b8cc-1361a446b0a5@pyr_str$5c432b4e-60e0-4288-8d5a-42e364ce8d16pyeval_$d3fe9870-ac9d-4871-b8cc-1361a446b0a5cell_execution_order $8e0722dc-6a3d-4cb3-ac8e-c527f123d0a7$6a35c5b8-2ce0-11ec-3a8c-b5a25bab9f9b$b59d932b-6425-47c2-a67d-208113bc8b7b$e07e4a47-a3cc-4ca4-a946-29e7df33ec6d$12814f02-7e90-401a-9573-5c6b2f8067ae$e8873c23-139d-41bc-be35-ebd636e48aee$005b40d9-bd89-4491-9807-d33a6c674b75$6449e96f-19ce-4100-8b35-56113bc24b7d$d9bc5dc1-67b6-47c6-9592-3b474ec451a0$56fcc0c2-0ce0-445b-b602-6525bab173b3$a1ada27d-8a1a-453a-ace7-ae07b68ad42a$56a3a022-6ed3-47d8-8d62-ce4ead5ca026$7576c6f6-3fc8-453a-b4c8-fe0c53b9ed7e$d3fe9870-ac9d-4871-b8cc-1361a446b0a5$b9903477-5070-43eb-82a9-8b750f79c8fa$fdd2e0ae-7ac9-4da7-9bfb-41d7cf76296b$688c93e7-b50f-4bb7-ab23-5686fd8ffb18$600344b6-ff43-431b-b858-2bf30e93d938$d74aed51-9542-47aa-8c3d-fb634c1a0212$71ca495d-39ad-4d52-94a5-d4248679ce1e$ab92a31d-1ef4-427f-b1c7-fa2790278a14$5c432b4e-60e0-4288-8d5a-42e364ce8d16$f93f0eef-bb0c-45ee-a080-e8eeb6611176$73c3f448-be7d-49b7-9e39-18c3a08feb01$f4d3b313-1c8c-4de1-b5bd-592cb1112068$dd20f208-0e39-4255-b35a-a8189986a165$5dc1c311-1004-4056-b0a9-06622546486e$21199966-adc3-498e-87ae-62333810efb5$216e88b3-82cb-4d74-aae4-c21791980ac2$fb3fb09d-1ba7-431e-aba2-f832d259075a$5f5ab869-c551-42d3-9325-86ecdc424c9blast_hot_reload_time        shortpathreactive python.jlprocess_statusreadypathH/home/runner/work/disorganised-mess/disorganised-mess/reactive python.jlpluto_versionv0.19.47last_save_timeAbACcell_order $e07e4a47-a3cc-4ca4-a946-29e7df33ec6d$73c3f448-be7d-49b7-9e39-18c3a08feb01$f93f0eef-bb0c-45ee-a080-e8eeb6611176$f4d3b313-1c8c-4de1-b5bd-592cb1112068$dd20f208-0e39-4255-b35a-a8189986a165$5dc1c311-1004-4056-b0a9-06622546486e$6a35c5b8-2ce0-11ec-3a8c-b5a25bab9f9b$8e0722dc-6a3d-4cb3-ac8e-c527f123d0a7$12814f02-7e90-401a-9573-5c6b2f8067ae$e8873c23-139d-41bc-be35-ebd636e48aee$005b40d9-bd89-4491-9807-d33a6c674b75$b59d932b-6425-47c2-a67d-208113bc8b7b$6449e96f-19ce-4100-8b35-56113bc24b7d$d9bc5dc1-67b6-47c6-9592-3b474ec451a0$71ca495d-39ad-4d52-94a5-d4248679ce1e$ab92a31d-1ef4-427f-b1c7-fa2790278a14$21199966-adc3-498e-87ae-62333810efb5$fdd2e0ae-7ac9-4da7-9bfb-41d7cf76296b$56fcc0c2-0ce0-445b-b602-6525bab173b3$a1ada27d-8a1a-453a-ace7-ae07b68ad42a$fb3fb09d-1ba7-431e-aba2-f832d259075a$216e88b3-82cb-4d74-aae4-c21791980ac2$56a3a022-6ed3-47d8-8d62-ce4ead5ca026$7576c6f6-3fc8-453a-b4c8-fe0c53b9ed7e$5c432b4e-60e0-4288-8d5a-42e364ce8d16$5f5ab869-c551-42d3-9325-86ecdc424c9b$d3fe9870-ac9d-4871-b8cc-1361a446b0a5$688c93e7-b50f-4bb7-ab23-5686fd8ffb18$b9903477-5070-43eb-82a9-8b750f79c8fa$600344b6-ff43-431b-b858-2bf30e93d938$d74aed51-9542-47aa-8c3d-fb634c1a0212published_objectsnbpkginstall_time_ns   C=ginstantiatedòinstalled_versionsPkgstdlibPlutoUI0.7.16PyCall1.92.3terminal_outputsPkg
[0m[1mInstantiating...[22m
[90m===[39m
[33m[1m┌ [22m[39m[33m[1mWarning: [22m[39mThe active manifest file is an older format with no julia version entry. Dependencies may have been resolved with a different julia version.
[33m[1m└ [22m[39m[90m@ /tmp/jl_9yyMyl/Manifest.toml:0[39m
[32m[1m   Installed[22m[39m PyCall ─────────── v1.92.3
            Installed           HypertextLiteral ─ v0.9.1                     [32m[1m[22m[39m
            Installed           Conda ──────────── v1.5.2                     [32m[1m[22m[39m
            Installed           VersionParsing ─── v1.2.0                     [32m[1m[22m[39m
[32m[1m   Installed[22m[39m Parsers ────────── v2.0.6
[32m[1m   Installed[22m[39m PlutoUI ────────── v0.7.16
             Building           Conda ─→ `~/.julia/scratchspaces/44cfe95a-1eb2-52ea-b672-e2afdf69b78f/299304989a5e6473d985212c28928899c74e9421/build.log`
             Building           PyCall → `~/.julia/scratchspaces/44cfe95a-1eb2-52ea-b672-e2afdf69b78f/169bb8ea6b1b143c5cf57df6d34d022a7b60c6db/build.log`
                                                                              
[0m[1mResolving...[22m
[90m===[39m
[33m[1m┌ [22m[39m[33m[1mWarning: [22m[39mThe active manifest file at `/tmp/jl_9yyMyl/Manifest.toml` has an old format that is being maintained.
[33m[1m│ [22m[39mTo update to the new format run `Pkg.upgrade_manifest()` which will upgrade the format without re-resolving.
[33m[1m└ [22m[39m[90m@ Pkg.Types /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.7/Pkg/src/manifest.jl:287[39m
[32m[1m  No Changes[22m[39m to `/tmp/jl_9yyMyl/Project.toml`
[32m[1m    Updating[22m[39m `/tmp/jl_9yyMyl/Manifest.toml`
 [90m [7b1f6079] [39m[92m+ FileWatching[39m
 [90m [e66e0078] [39m[92m+ CompilerSupportLibraries_jll[39m
 [90m [4536629a] [39m[92m+ OpenBLAS_jll[39m
 [90m [8e850b90] [39m[92m+ libblastrampoline_jll[39m

[0m[1mPrecompiling...[22m
[90m===[39m
[32m[1m  Activating[22m[39m project at `/tmp/jl_9yyMyl`
[32m[1mPrecompiling[22m[39m project...
  3 dependencies successfully precompiled in 6 seconds (14 already precompiled)nbpkg_sync
[0m[1mInstantiating...[22m
[90m===[39m
[33m[1m┌ [22m[39m[33m[1mWarning: [22m[39mThe active manifest file is an older format with no julia version entry. Dependencies may have been resolved with a different julia version.
[33m[1m└ [22m[39m[90m@ /tmp/jl_9yyMyl/Manifest.toml:0[39m
[32m[1m   Installed[22m[39m PyCall ─────────── v1.92.3
            Installed           HypertextLiteral ─ v0.9.1                     [32m[1m[22m[39m
            Installed           Conda ──────────── v1.5.2                     [32m[1m[22m[39m
            Installed           VersionParsing ─── v1.2.0                     [32m[1m[22m[39m
[32m[1m   Installed[22m[39m Parsers ────────── v2.0.6
[32m[1m   Installed[22m[39m PlutoUI ────────── v0.7.16
             Building           Conda ─→ `~/.julia/scratchspaces/44cfe95a-1eb2-52ea-b672-e2afdf69b78f/299304989a5e6473d985212c28928899c74e9421/build.log`
             Building           PyCall → `~/.julia/scratchspaces/44cfe95a-1eb2-52ea-b672-e2afdf69b78f/169bb8ea6b1b143c5cf57df6d34d022a7b60c6db/build.log`
                                                                              
[0m[1mResolving...[22m
[90m===[39m
[33m[1m┌ [22m[39m[33m[1mWarning: [22m[39mThe active manifest file at `/tmp/jl_9yyMyl/Manifest.toml` has an old format that is being maintained.
[33m[1m│ [22m[39mTo update to the new format run `Pkg.upgrade_manifest()` which will upgrade the format without re-resolving.
[33m[1m└ [22m[39m[90m@ Pkg.Types /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.7/Pkg/src/manifest.jl:287[39m
[32m[1m  No Changes[22m[39m to `/tmp/jl_9yyMyl/Project.toml`
[32m[1m    Updating[22m[39m `/tmp/jl_9yyMyl/Manifest.toml`
 [90m [7b1f6079] [39m[92m+ FileWatching[39m
 [90m [e66e0078] [39m[92m+ CompilerSupportLibraries_jll[39m
 [90m [4536629a] [39m[92m+ OpenBLAS_jll[39m
 [90m [8e850b90] [39m[92m+ libblastrampoline_jll[39m

[0m[1mPrecompiling...[22m
[90m===[39m
[32m[1m  Activating[22m[39m project at `/tmp/jl_9yyMyl`
[32m[1mPrecompiling[22m[39m project...
  3 dependencies successfully precompiled in 6 seconds (14 already precompiled)PlutoUI
[0m[1mInstantiating...[22m
[90m===[39m
[33m[1m┌ [22m[39m[33m[1mWarning: [22m[39mThe active manifest file is an older format with no julia version entry. Dependencies may have been resolved with a different julia version.
[33m[1m└ [22m[39m[90m@ /tmp/jl_9yyMyl/Manifest.toml:0[39m
[32m[1m   Installed[22m[39m PyCall ─────────── v1.92.3
            Installed           HypertextLiteral ─ v0.9.1                     [32m[1m[22m[39m
            Installed           Conda ──────────── v1.5.2                     [32m[1m[22m[39m
            Installed           VersionParsing ─── v1.2.0                     [32m[1m[22m[39m
[32m[1m   Installed[22m[39m Parsers ────────── v2.0.6
[32m[1m   Installed[22m[39m PlutoUI ────────── v0.7.16
             Building           Conda ─→ `~/.julia/scratchspaces/44cfe95a-1eb2-52ea-b672-e2afdf69b78f/299304989a5e6473d985212c28928899c74e9421/build.log`
             Building           PyCall → `~/.julia/scratchspaces/44cfe95a-1eb2-52ea-b672-e2afdf69b78f/169bb8ea6b1b143c5cf57df6d34d022a7b60c6db/build.log`
                                                                              
[0m[1mResolving...[22m
[90m===[39m
[33m[1m┌ [22m[39m[33m[1mWarning: [22m[39mThe active manifest file at `/tmp/jl_9yyMyl/Manifest.toml` has an old format that is being maintained.
[33m[1m│ [22m[39mTo update to the new format run `Pkg.upgrade_manifest()` which will upgrade the format without re-resolving.
[33m[1m└ [22m[39m[90m@ Pkg.Types /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.7/Pkg/src/manifest.jl:287[39m
[32m[1m  No Changes[22m[39m to `/tmp/jl_9yyMyl/Project.toml`
[32m[1m    Updating[22m[39m `/tmp/jl_9yyMyl/Manifest.toml`
 [90m [7b1f6079] [39m[92m+ FileWatching[39m
 [90m [e66e0078] [39m[92m+ CompilerSupportLibraries_jll[39m
 [90m [4536629a] [39m[92m+ OpenBLAS_jll[39m
 [90m [8e850b90] [39m[92m+ libblastrampoline_jll[39m

[0m[1mPrecompiling...[22m
[90m===[39m
[32m[1m  Activating[22m[39m project at `/tmp/jl_9yyMyl`
[32m[1mPrecompiling[22m[39m project...
  3 dependencies successfully precompiled in 6 seconds (14 already precompiled)PyCall
[0m[1mInstantiating...[22m
[90m===[39m
[33m[1m┌ [22m[39m[33m[1mWarning: [22m[39mThe active manifest file is an older format with no julia version entry. Dependencies may have been resolved with a different julia version.
[33m[1m└ [22m[39m[90m@ /tmp/jl_9yyMyl/Manifest.toml:0[39m
[32m[1m   Installed[22m[39m PyCall ─────────── v1.92.3
            Installed           HypertextLiteral ─ v0.9.1                     [32m[1m[22m[39m
            Installed           Conda ──────────── v1.5.2                     [32m[1m[22m[39m
            Installed           VersionParsing ─── v1.2.0                     [32m[1m[22m[39m
[32m[1m   Installed[22m[39m Parsers ────────── v2.0.6
[32m[1m   Installed[22m[39m PlutoUI ────────── v0.7.16
             Building           Conda ─→ `~/.julia/scratchspaces/44cfe95a-1eb2-52ea-b672-e2afdf69b78f/299304989a5e6473d985212c28928899c74e9421/build.log`
             Building           PyCall → `~/.julia/scratchspaces/44cfe95a-1eb2-52ea-b672-e2afdf69b78f/169bb8ea6b1b143c5cf57df6d34d022a7b60c6db/build.log`
                                                                              
[0m[1mResolving...[22m
[90m===[39m
[33m[1m┌ [22m[39m[33m[1mWarning: [22m[39mThe active manifest file at `/tmp/jl_9yyMyl/Manifest.toml` has an old format that is being maintained.
[33m[1m│ [22m[39mTo update to the new format run `Pkg.upgrade_manifest()` which will upgrade the format without re-resolving.
[33m[1m└ [22m[39m[90m@ Pkg.Types /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.7/Pkg/src/manifest.jl:287[39m
[32m[1m  No Changes[22m[39m to `/tmp/jl_9yyMyl/Project.toml`
[32m[1m    Updating[22m[39m `/tmp/jl_9yyMyl/Manifest.toml`
 [90m [7b1f6079] [39m[92m+ FileWatching[39m
 [90m [e66e0078] [39m[92m+ CompilerSupportLibraries_jll[39m
 [90m [4536629a] [39m[92m+ OpenBLAS_jll[39m
 [90m [8e850b90] [39m[92m+ libblastrampoline_jll[39m

[0m[1mPrecompiling...[22m
[90m===[39m
[32m[1m  Activating[22m[39m project at `/tmp/jl_9yyMyl`
[32m[1mPrecompiling[22m[39m project...
  3 dependencies successfully precompiled in 6 seconds (14 already precompiled)enabled÷restart_recommended_msgrestart_required_msgbusy_packageswaiting_for_permission,waiting_for_permission_but_probably_disabled«cell_inputs $005b40d9-bd89-4491-9807-d33a6c674b75cell_id$005b40d9-bd89-4491-9807-d33a6c674b75code-begin
	py"""
	import math
	math.sin"""(2)
endmetadatashow_logsèdisabled®skip_as_script«code_folded$12814f02-7e90-401a-9573-5c6b2f8067aecell_id$12814f02-7e90-401a-9573-5c6b2f8067aecode# Pkg.build("PyCall")metadatashow_logsèdisabled®skip_as_script«code_folded$6449e96f-19ce-4100-8b35-56113bc24b7dcell_id$6449e96f-19ce-4100-8b35-56113bc24b7dcodeDump(:(py"[1+1]"))metadatashow_logsèdisabled®skip_as_script«code_folded$5f5ab869-c551-42d3-9325-86ecdc424c9bcell_id$5f5ab869-c551-42d3-9325-86ecdc424c9bcodemacro pyr_old_str(str)
	var"@custom_py_str"
	
	reads, writes = py_reads_writes(str)

	quote
		if false
		$([esc(:($(Symbol("#py", s)) = 1))  for s in writes]...)
		$([esc(:($(Symbol("#py", s))))  for s in reads]...)
		end
		@custom_py_str($(str))
	end
endmetadatashow_logsèdisabled®skip_as_script«code_folded$56a3a022-6ed3-47d8-8d62-ce4ead5ca026cell_id$56a3a022-6ed3-47d8-8d62-ce4ead5ca026codebBase.remove_linenums!(Meta.macroexpand(@__MODULE__, :(pyr"""
x = 123
y = b
"""); recursive=false))metadatashow_logsèdisabled®skip_as_script«code_folded$e07e4a47-a3cc-4ca4-a946-29e7df33ec6dcell_id$e07e4a47-a3cc-4ca4-a946-29e7df33ec6dcodemd"""
# Reactive Python

The `pyr"` macro is just like the `py"` macro from `PyCall.jl`, except it is reactive! This means:
- If you define a Python variable, then other cells that use that python variable are also evaluated.
- The scope of Python variables is cleaned up automatically.
- Multiple definitions are not allowed.

This is using the Python port of Pluto.ExpressionExplorer by Mikołaj Bochenski: [https://github.com/lightning-notebook/engine](https://github.com/lightning-notebook/engine) and some Julia macro magic.
"""metadatashow_logsèdisabled®skip_as_script«code_folded$56fcc0c2-0ce0-445b-b602-6525bab173b3cell_id$56fcc0c2-0ce0-445b-b602-6525bab173b3code2begin
	rand(), try
		var"#py_var_x"
	catch end
endmetadatashow_logsèdisabled®skip_as_script«code_folded$21199966-adc3-498e-87ae-62333810efb5cell_id$21199966-adc3-498e-87ae-62333810efb5code%@macroexpand pyr"""
x = 123
y = b
"""metadatashow_logsèdisabled®skip_as_script«code_folded$73c3f448-be7d-49b7-9e39-18c3a08feb01cell_id$73c3f448-be7d-49b7-9e39-18c3a08feb01codepyr"""
y = x + x
"""metadatashow_logsèdisabled®skip_as_script«code_folded$fb3fb09d-1ba7-431e-aba2-f832d259075acell_id$fb3fb09d-1ba7-431e-aba2-f832d259075acodepyr"f(1)"metadatashow_logsèdisabled®skip_as_script«code_folded$8e0722dc-6a3d-4cb3-ac8e-c527f123d0a7cell_id$8e0722dc-6a3d-4cb3-ac8e-c527f123d0a7codeimport Pkgmetadatashow_logsèdisabled®skip_as_script«code_folded$600344b6-ff43-431b-b858-2bf30e93d938cell_id$600344b6-ff43-431b-b858-2bf30e93d938codemd"""
Following code is from [https://github.com/lightning-notebook/engine/blob/master/tests/test_variable_access.py](https://github.com/lightning-notebook/engine/blob/master/tests/test_variable_access.py)
"""metadatashow_logsèdisabled®skip_as_script«code_folded$688c93e7-b50f-4bb7-ab23-5686fd8ffb18cell_id$688c93e7-b50f-4bb7-ab23-5686fd8ffb18codecustom_py"""
1 + 1"""metadatashow_logsèdisabled®skip_as_script«code_folded$a1ada27d-8a1a-453a-ace7-ae07b68ad42acell_id$a1ada27d-8a1a-453a-ace7-ae07b68ad42acode123metadatashow_logsèdisabled®skip_as_script«code_folded$b9903477-5070-43eb-82a9-8b750f79c8facell_id$b9903477-5070-43eb-82a9-8b750f79c8facodemacro custom_py_str(code, options...)
    T = length(options) == 1 && 'o' in options[1] ? PyObject : PyAny
    code, locals = interpolate_pycode(code)
    input_type = '\n' in code ? Py_file_input : Py_eval_input
    fname = make_fname(@__FILE__)
    assignlocals = Expr(:block, [(isa(v,String) ?
                                  :(m[$v] = PyObject($(esc(ex)))) :
                                  nothing) for (v,ex) in locals]...)
    code_expr = Expr(:call, esc(:(Base.string)))
    i0 = firstindex(code)
    for i in sort!(collect(filter(k -> isa(k,Integer), keys(locals))))
        push!(code_expr.args, code[i0:prevind(code,i)], esc(locals[i]))
        i0 = i
    end
    push!(code_expr.args, code[i0:lastindex(code)])
    if input_type == Py_eval_input
        removelocals = Expr(:block, [:(delete!(m, $v)) for v in keys(locals)]...)
    else
        # if we are evaluating multi-line input, then it is not
        # safe to remove the local variables, because they might be referred
        # to in Python function definitions etc. that will be called later.
        removelocals = nothing
    end
    quote
        m = pynamespace(Main)
        $assignlocals
        ret = $T(pyeval_($code_expr, m, m, $input_type, $fname))
        $removelocals
        ret
    end
endmetadatashow_logsèdisabled®skip_as_script«code_folded$71ca495d-39ad-4d52-94a5-d4248679ce1ecell_id$71ca495d-39ad-4d52-94a5-d4248679ce1ecoderw = py_reads_writes("x=2")metadatashow_logsèdisabled®skip_as_script«code_folded$5c432b4e-60e0-4288-8d5a-42e364ce8d16cell_id$5c432b4e-60e0-4288-8d5a-42e364ce8d16codemacro pyr_str(str)
	var"@custom_py_str"
	
	reads, writes = py_reads_writes(str)

	quote
		# if false
		$([let
			julia_s = Symbol("py#var_", py_s)
			import_code = """$(py_s) = \$(s)\n"""
			esc(quote
				let s = $(julia_s) # for pluto to recognise
				@custom_py_str($(import_code)) # load stored PyObject into python using that name
				end
			end)
		end for py_s in reads]...)
		# end
		
		output = @custom_py_str($(str))
		
		# if false

		$([let
			julia_s = Symbol("py#var_", py_s)
			import_code = "$(py_s)"
			esc(quote
				$(julia_s) = @custom_py_str($(import_code)) # store PyObject as julia object, so that it can use Pluto's reactivity
			end)
		end for py_s in writes]...)
		# end
		output
	end
endmetadatashow_logsèdisabled®skip_as_script«code_folded$f4d3b313-1c8c-4de1-b5bd-592cb1112068cell_id$f4d3b313-1c8c-4de1-b5bd-592cb1112068codepyr"[x, y]"metadatashow_logsèdisabled®skip_as_script«code_folded$5dc1c311-1004-4056-b0a9-06622546486ecell_id$5dc1c311-1004-4056-b0a9-06622546486ecodepyr"cool(x, x)"metadatashow_logsèdisabled®skip_as_script«code_folded$7576c6f6-3fc8-453a-b4c8-fe0c53b9ed7ecell_id$7576c6f6-3fc8-453a-b4c8-fe0c53b9ed7ecode%# string(Expr(:symbol, Symbol("#a")))metadatashow_logsèdisabled®skip_as_script«code_folded$6a35c5b8-2ce0-11ec-3a8c-b5a25bab9f9bcell_id$6a35c5b8-2ce0-11ec-3a8c-b5a25bab9f9bcodeusing PyCallmetadatashow_logsèdisabled®skip_as_script«code_folded$d9bc5dc1-67b6-47c6-9592-3b474ec451a0cell_id$d9bc5dc1-67b6-47c6-9592-3b474ec451a0codeDump(:(py"""
[1+1]
"""))metadatashow_logsèdisabled®skip_as_script«code_folded$e8873c23-139d-41bc-be35-ebd636e48aeecell_id$e8873c23-139d-41bc-be35-ebd636e48aeecode=begin
	py"""
	import math
	math.sin
	"""
	py"math.sin"(2)
endmetadatashow_logsèdisabled®skip_as_script«code_folded$d74aed51-9542-47aa-8c3d-fb634c1a0212cell_id$d74aed51-9542-47aa-8c3d-fb634c1a0212codepy_reads_writes = begin
	py"""
	import ast
	import functools
	
	
	
	class VariableAccess:
	    def __init__(self, reads, writes):
	        self.reads = frozenset(reads)
	        self.writes = frozenset(writes)
	    
	
	    @classmethod
	    def from_code(cls, code):
	        return cls.from_ast(ast.parse(code))
	    
	
	    @classmethod
	    def from_ast(cls, ast_node):
	        if isinstance(ast_node, ast.Name):
	            return cls(reads=[ast_node.id], writes=[])
	
	        if isinstance(ast_node, ast.Assign):
	            targets = cls.from_ast(ast_node.targets)
	            value = cls.from_ast(ast_node.value)
	            return cls(reads=value.reads, writes=targets.reads | targets.writes | value.writes)
	        if isinstance(ast_node, ast.AugAssign): # x += 3, for example
	            target = cls.from_ast(ast_node.target)
	            value = cls.from_ast(ast_node.value)
	            return cls(reads=value.reads, writes=target.reads | target.writes | value.writes)
	        
	        if isinstance(ast_node, ast.ImportFrom):
	            if ast_node.names[0].name == '*':
	                raise NotImplementedError('"import *" is not supported yet!')
	            return cls.from_ast(ast_node.names)
	        if isinstance(ast_node, ast.alias):
	            return cls(reads=[], writes=[ast_node.asname or ast_node.name])
	        
	        if isinstance(ast_node, ast.ClassDef):
	            bases = cls.from_ast(ast_node.bases)
	            keywords = cls.from_ast(ast_node.keywords)
	            decorators = cls.from_ast(ast_node.decorator_list)
	            body = cls.from_ast(ast_node.body) # no name shadowing because of "if x: y = 10"
	            return cls(
	                reads=bases.reads | keywords.reads | decorators.reads | body.reads,
	                writes=[ast_node.name]
	            )
	        
	        if isinstance(ast_node, ast.Lambda):
	            arguments = cls.from_ast(ast_node.args)
	            body = cls.from_ast(ast_node.body)
	            return cls(reads=arguments.reads | (body.reads - arguments.writes), writes=[])
	        if isinstance(ast_node, ast.FunctionDef):
	            decorators = cls.from_ast(ast_node.decorator_list)
	            arguments = cls.from_ast(ast_node.args)
	            body = cls.from_ast(ast_node.body)
	            return cls(reads=decorators.reads | arguments.reads | (body.reads - arguments.writes), writes=[ast_node.name])
	        if isinstance(ast_node, ast.arg):
	            return cls(reads=[], writes=[ast_node.arg])
	
	        if isinstance(ast_node, ast.For):
	            target = cls.from_ast(ast_node.target) # no name shadowing - target is actually written to
	            iterable = cls.from_ast(ast_node.iter)
	            body = cls.from_ast(ast_node.body)
	            else_body = cls.from_ast(ast_node.orelse)
	            return cls(
	                reads=iterable.reads | body.reads | else_body.reads,
	                writes=target.reads | target.writes | iterable.writes | body.writes | else_body.writes
	            )
	        
	        if isinstance(ast_node, ast.ListComp):
	            element = cls.from_ast(ast_node.elt)
	            generators = cls.from_ast(ast_node.generators)
	            return element | generators # TODO: name shadowing
	        if isinstance(ast_node, ast.SetComp):
	            element = cls.from_ast(ast_node.elt)
	            generators = cls.from_ast(ast_node.generators)
	            return element | generators # TODO: name shadowing
	        if isinstance(ast_node, ast.DictComp):
	            key = cls.from_ast(ast_node.key)
	            value = cls.from_ast(ast_node.value)
	            generators = cls.from_ast(ast_node.generators)
	            return key | value | generators # TODO: name shadowing
	        if isinstance(ast_node, ast.comprehension):
	            target = cls.from_ast(ast_node.target)
	            iterable = cls.from_ast(ast_node.iter)
	            conditions = cls.from_ast(ast_node.ifs)
	            return target | iterable | conditions # TODO: name shadowing
	        
	        if isinstance(ast_node, list):
	            return functools.reduce(
	                cls.__or__,
	                [cls.from_ast(sub_ast) for sub_ast in ast_node],
	                cls(reads=[], writes=[])
	            )
	        
	        for node_type, children in node_children.items():
	            if isinstance(ast_node, node_type):
	                return cls.from_ast([getattr(ast_node, child) for child in children])
	        
	        raise NotImplementedError(f'Cannot parse {type(ast_node)} yet!')
	
	
	    def __eq__(self, other):
	        return self.reads == other.reads and self.writes == other.writes
	
	
	    def __or__(self, other):
	        return type(self)(reads=self.reads | other.reads, writes=self.writes | other.writes)
	    
	
	    def __repr__(self):
	        return f'{type(self).__name__}(reads={list(self.reads)}, writes={list(self.writes)})'
	
	
	node_children = {
	    ast.Constant: [],
	    ast.Pass: [],
	    type(None): [],
	    ast.Expression: ['body'],
	    ast.Expr: ['value'],
	    ast.Module: ['body'],
	    ast.Import: ['names'],
	    ast.Attribute: ['value'],
	    ast.arguments: ['posonlyargs', 'args', 'vararg', 'kwonlyargs', 'kwarg', 'defaults', 'kw_defaults'],
	    ast.Return: ['value'],
	    ast.Call: ['func', 'args', 'keywords'],
	    ast.keyword: ['value'],
	    ast.If: ['test', 'body', 'orelse'],
	    ast.IfExp: ['test', 'body', 'orelse'],
	    ast.While: ['test', 'body', 'orelse'],
	    ast.Tuple: ['elts'],
	    ast.List: ['elts'],
	    ast.Set: ['elts'],
	    ast.Dict: ['keys', 'values'],
	    ast.JoinedStr: ['values'],
	    ast.FormattedValue: ['value'],
	    ast.Subscript: ['value', 'slice'],
	    ast.Index: ['value'],
	    ast.Slice: ['lower', 'upper', 'step'],
	    ast.UnaryOp: ['operand'],
	    ast.BinOp: ['left', 'right'],
	    ast.BoolOp: ['values'],
	    ast.Compare: ['left', 'comparators']
	}

	def reads_writes(code):
		va = VariableAccess.from_code(code)
		return [va.reads, va.writes]
	"""
	
	py"reads_writes"
endmetadatashow_logsèdisabled®skip_as_script«code_folded$ab92a31d-1ef4-427f-b1c7-fa2790278a14cell_id$ab92a31d-1ef4-427f-b1c7-fa2790278a14coderw[2] |> collectmetadatashow_logsèdisabled®skip_as_script«code_folded$b59d932b-6425-47c2-a67d-208113bc8b7bcell_id$b59d932b-6425-47c2-a67d-208113bc8b7bcodeusing PlutoUImetadatashow_logsèdisabled®skip_as_script«code_folded$fdd2e0ae-7ac9-4da7-9bfb-41d7cf76296bcell_id$fdd2e0ae-7ac9-4da7-9bfb-41d7cf76296bcode2begin
	custom_py"""
	x = 3
	"""

	custom_py"x"
endmetadatashow_logsèdisabled®skip_as_script«code_folded$d3fe9870-ac9d-4871-b8cc-1361a446b0a5cell_id$d3fe9870-ac9d-4871-b8cc-1361a446b0a5codeaimport PyCall: interpolate_pycode, Py_file_input, make_fname, Py_eval_input, pynamespace, pyeval_metadatashow_logsèdisabled®skip_as_script«code_folded$dd20f208-0e39-4255-b35a-a8189986a165cell_id$dd20f208-0e39-4255-b35a-a8189986a165code)pyr"""
def cool(x, y):
	return 123123
"""metadatashow_logsèdisabled®skip_as_script«code_folded$f93f0eef-bb0c-45ee-a080-e8eeb6611176cell_id$f93f0eef-bb0c-45ee-a080-e8eeb6611176codepyr"""
x = 2
"""metadatashow_logsèdisabled®skip_as_script«code_folded$216e88b3-82cb-4d74-aae4-c21791980ac2cell_id$216e88b3-82cb-4d74-aae4-c21791980ac2code(pyr"""
def f(x):
	return x + 1123123
"""metadatashow_logsèdisabled®skip_as_script«code_folded«notebook_id$410e9fe0-4aa1-11f0-23e4-ebbda5fc8a98in_temp_dir¨metadata